package com.gopay.checkorder.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.task.BankCountDownLatch;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.BocConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.boc.ebank.BocB2cMessage;
import com.gopay.common.domain.bank.boc.ebank.BocDayEndMessage;
import com.gopay.common.domain.bank.boc.ebank.dayend.BocB2cDayendEntry;
import com.gopay.common.domain.bank.dayend.BaseDayendEntry;
import com.gopay.common.domain.cashier.BankCardType;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.domain.cps.vo.InAccInfo;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.NumberUtils;
import com.gopay.remote.bank.BankInteractRemoteService;

/**
 * @CheckOrderBocB2cImpl.java
 * @author wanggang
 * @2013-11-12 下午2:37:28 www.gopay.com.cn Inc.All rights reserved.
 */
public class CheckOrderBocB2cImpl implements BankOrderService {

	private final static Logger logger = LoggerFactory.getLogger(CheckOrderBocB2cImpl.class);
	@Resource(name = "bankClient")
	private BankInteractRemoteService bankClient;

	@Override
	public Result getDayendMsg(String bank_bus) {
		String bank = bank_bus.split("-")[0];
		BocDayEndMessage dayendMsg = new BocDayEndMessage();
		dayendMsg.setFileDate(DateUtils.date2string(new Date(), "yyyyMMdd"));
		dayendMsg.setBank(bank);
		dayendMsg.setTradeType(2);
		Result re = bankClient.dayend(dayendMsg);
		return re;
	}

	@Override
	public CheckOrderResult checkOrder(BankOrder bankOrder, String target) {
		CheckOrderResult checkOrderResult = new CheckOrderResult();
		checkOrderResult.setSuccess(false);
		checkOrderResult.setOrderId(bankOrder.getOrderId());
		try {
			BocB2cMessage base = new BocB2cMessage();
			base.setOrderId(bankOrder.getOrderId());
			base.setBankOrderId(bankOrder.getOutOrderId());
			base.setBank(BankConstants.BANK_LOGO_BOC);
			base.setBankIntrChann(BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()));
			base.setBankBusProd(BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
			Result result = new Result();
			result = bankClient.query(base);

			if (result == null || !result.isSuccess()) {
				logger.debug("bankClient fail.");

				if (result == null || ProcCodeConstants.PROC_CODE_100E6037.equals(result.getResultCode())) {
					BankCountDownLatch.failIncrease(bankOrder.getBankCode());
					checkOrderResult.setCommunicateError(true);
				}

				logger.debug(ToStringBuilder.reflectionToString(result, ToStringStyle.DEFAULT_STYLE));
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
				checkOrderResult.setErrMsg("系统返回对账结果为空");

				return checkOrderResult;
			}

			BocB2cMessage res = (BocB2cMessage) result.getDefaultModel();
			if (res == null) {
				// 查询订单为空
				logger.debug("fail:orderId:" + bankOrder.getOrderId() + " errcode:" + ProcCodeConstants.PROC_CODE_100E5062 + " err:bis query is null.");
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg("银行返回对账结果为空");
			}

			if (StringUtils.isNotBlank(res.getException())) {
				// 查询订单错误
				logger.debug("fail:orderId:" + bankOrder.getOrderId() + " merchantNo:" + res.getMerchantNo() + " errMsg:" + res.getException());
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
				checkOrderResult.setErrMsg(res.getException());
				return checkOrderResult;
			}
			// 中行返回结果数据集，我平台一次只查一笔
			List<BocB2cMessage> bocB2cMessageList = res.getList();
			if (bocB2cMessageList != null && bocB2cMessageList.size() > 0) {
				BocB2cMessage orderRes = (BocB2cMessage) res.getList().get(0);
				checkOrderResult.setOrderId(orderRes.getOrderId());
				checkOrderResult.setAmount(NumberUtils.getNum(orderRes.getPayAmount()));
				// 失败处理
				if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_FAIL, orderRes.getOrderStatus())) {
					checkOrderResult.setBankFailure(true);
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易失败");
					checkOrderResult.setErrMsg("交易失败");
				}
				// 成功处理
				else if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_PAY, orderRes.getOrderStatus())) {
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易成功");
					checkOrderResult.setSuccess(true);
					InAccInfo accInfo = new InAccInfo();
					accInfo.setOrderId(bankOrder.getOrderId());
					accInfo.setAmount(NumberUtils.getNum(orderRes.getPayAmount()));
					accInfo.setRetCode("00");
					accInfo.setCardType(BankCardType.Unknown.toString());
					checkOrderResult.setAccInfo(accInfo);
				}
				// 不处理
				else if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_UNDEAL, orderRes.getOrderStatus())) {
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易未做处理");
					checkOrderResult.setErrMsg("银行返回交易未做处理");
				} else if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_CANCEL, orderRes.getOrderStatus())) {
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易被撤销");
					checkOrderResult.setErrMsg("银行返回交易被撤销");
				} else if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_RETURN_GOODS, orderRes.getOrderStatus())) {
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易退货");
					checkOrderResult.setErrMsg("银行返回交易退货");
				} else if (StringUtils.equals(BocConstants.B2C_ORDER_STATUS_UNKNOW, orderRes.getOrderStatus())) {
					logger.info("中行B2C订单" + orderRes.getOrderId() + "的交易发生未明情况");
					checkOrderResult.setErrMsg("银行返回交易发生未明情况");
				} else {
					logger.info("中行B2C	订单" + orderRes.getOrderId() + "交易发生异常！跳出");
					// 银行订单状态为失败
					checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5062);
					checkOrderResult.setErrMsg("银行返回订单查询失败");
				}
			}
			return checkOrderResult;
		} catch (Exception e) {
			logger.debug("bankClient fail.", e);
			checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
			checkOrderResult.setErrMsg("对账调用bis失败");
			return checkOrderResult;
		}
	}

	/**
	 * @author guomuye
	 * 一笔一笔的对 第一个参数是日终的一条订单记录 第二个参数是根据日终订单记录中的订单号获取的本地数据库订单的记录
	 */
	@Override
	public CheckOrderResult checkDayendOrder(BaseDayendEntry bdm, BankOrder bo) {
		CheckOrderResult checkOrderResult = new CheckOrderResult(true);
		BocB2cDayendEntry entry = (BocB2cDayendEntry) bdm;
		String dayendOrderStatus = entry.getOrderStatus();
		String nativeDBOrderStatus = bo.getOrderStatus();
		
		// 银行到本地订单状态转换
		if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_PAY)) {
			dayendOrderStatus = BankOrderStatus.BANK_CALL_SUCCESS;
		} else if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_UNDEAL)) {
			dayendOrderStatus = BankOrderStatus.PROCESS;
		} else if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_RETURN_GOODS)) {
			dayendOrderStatus = BankOrderStatus.PROCESS;
		} else if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_UNKNOW)) {
			dayendOrderStatus = BankOrderStatus.PROCESS;
		} else if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_CANCEL)) {
			dayendOrderStatus = BankOrderStatus.PROCESS;
		} else if (StringUtils.equals(dayendOrderStatus, BocConstants.B2C_ORDER_STATUS_FAIL)) {
			dayendOrderStatus = BankOrderStatus.FAIL;
		} else {
			checkOrderResult.setSuccess(false);
			checkOrderResult.setOrderId(bo.getOutOrderId());
			checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_300G1013);
			checkOrderResult.setErrMsg("银行订单出现新订单状态" + dayendOrderStatus);
			checkOrderResult.setAmount(new BigDecimal(NumberUtils.formatNum(entry.getAccount())));
			logger.info("中行B2C订单" + bo.getOutOrderId() + "新订单状态" + dayendOrderStatus);
			return checkOrderResult;
		}
		
		if (StringUtils.equals(dayendOrderStatus, BankOrderStatus.FAIL)) {
			if (StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.BANK_CALL_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.AUTO_CHECK_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.BPS_CHECK_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.CHECK_SUCCESS)) {
				checkOrderResult.setSuccess(false);
				checkOrderResult.setOrderId(bo.getOutOrderId());
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_300G1012);
				checkOrderResult.setErrMsg("对单失败:银行订单状态:" + dayendOrderStatus + "-失败:: 本地订单状态: " + nativeDBOrderStatus+"-成功");
				checkOrderResult.setAmount(new BigDecimal(NumberUtils.formatNum(entry.getAccount())));
				logger.info("中行B2C订单" + bo.getOutOrderId() + "对单失败" + "银行订单状态:" + dayendOrderStatus + "-失败:: 本地订单状态:" + nativeDBOrderStatus+"-成功");
				return checkOrderResult;
			}
		} else if (StringUtils.equals(dayendOrderStatus, BankOrderStatus.PROCESS)) {
			if (StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.BANK_CALL_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.AUTO_CHECK_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.BPS_CHECK_SUCCESS) || StringUtils.endsWith(nativeDBOrderStatus, BankOrderStatus.CHECK_SUCCESS)) {
				checkOrderResult.setSuccess(false);
				checkOrderResult.setOrderId(bo.getOutOrderId());
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_300G1012);
				checkOrderResult.setErrMsg("对单失败:银行订单状态:" + dayendOrderStatus + "-正在进行:: 本地订单状态: " + nativeDBOrderStatus+"-成功");
				checkOrderResult.setAmount(new BigDecimal(NumberUtils.formatNum(entry.getAccount())));
				logger.info("中行B2C订单" + bo.getOutOrderId() + "对单失败" + "银行订单状态:" + dayendOrderStatus + "-正在进行:: 本地订单状态:" + nativeDBOrderStatus+"-成功");
				return checkOrderResult;
			}
		}else if (StringUtils.equals(dayendOrderStatus, BankOrderStatus.BANK_CALL_SUCCESS)) {
			if (StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.FAIL) || StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.BPS_CHECK_FAIL) || StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.ORDER_FAIL)|| StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.VERIFY_FAIL)|| StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.CANCEL) || StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.AMOUNT_ERROR)|| StringUtils.equals(nativeDBOrderStatus, BankOrderStatus.TIMEOUT)) {
				checkOrderResult.setSuccess(false);
				checkOrderResult.setOrderId(bo.getOutOrderId());
				checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_300G1012);
				checkOrderResult.setErrMsg("对单失败:银行订单状态:" + dayendOrderStatus + "-成功:: 本地订单状态: " + nativeDBOrderStatus+"-失败");
				checkOrderResult.setAmount(new BigDecimal(NumberUtils.formatNum(entry.getAccount())));
				logger.info("中行B2C订单" + bo.getOutOrderId() + "对单失败" + "银行订单状态:" + dayendOrderStatus + "-成功:: 本地订单状态:" + nativeDBOrderStatus+"-失败");
				return checkOrderResult;
			}
		}
		return checkOrderResult;
		
	}

	@Override
	public List<CheckOrderResult> checkDayend(String bank_bus) {
		return null;
	}

	@Override
	public BankOrder getDbOrder() {
		return null;
	}

	@Override
	public BaseMessage dayend(String bank_bus) {
		// TODO Auto-generated method stub
		return null;
	}


}
